用户定义类型
C++解决这个问题的方式就是允许用户直接定义类型,这种类型的行为方式(几乎)与内部类型完全一样。这样的类型常常被称做抽象数据类型,而我更喜欢术语用户定义类型。有关抽象数据类型的一个更合理的定义应当要求一个数学的“抽象”描述。给出了一个这样的描述之后,我们这里所谓的类型就是那种真正抽象实例的一个具体实例。现在程序设计范型变成了:
确定你需要哪些类型;为每个类型提供完整的一组操作。
在那些对于每个类型都只需要一个对象的地方,采用模块方式实现数据隐藏风格的程序设计也就足够了。
各种算术类型,例如有理数或复数,是用户定义类型的最常见实例。例如,
class complex
{
double re, im;
public:
// 从两个标量构造一个复数
complex(double r, double i) { re = r; im = i; }
complex(double r) { re = r; im = 0; }
complex() { re = im = 0; }
friend complex operator+(complex, complex);
friend complex operator-(complex, complex); // 二元
friend complex operator-(complex); // 一元
friend complex operator*(complex, complex);
friend complex operator/(complex, complex);
friend bool operator==(complex, complex); // 等于
friend bool operator!=(complex, complex); // 不等于
// ...
};
类(也就是用户定义类型)complex的声明描述了一个复数的表示,以及一组对复数的操作。这个表示是私用的,也就是说,re
和 im
只能由类complex的声明里描述的那些函数访问。有关的函数可以按如下方式定义:
complex operator+(complex a1, complex a2)
{
return complex(a1.re + a2,re, a1.im + a2.im);
}
名字与类名相同的成员函数被称为构造函数。每个构造函数定义了一种初始化这个类的对象的方式。类complex提供了三个构造函数,其中一个从一个double做出了一个complex,另一个从一对double做出一个complex,第三个做出一个具有默认值的complex。
类complex可以按如下方式使用:
void f(complex z)
{
complex a = 2.3;
complex b = 1/a;
complex c = a + b * complex(1, 2.3);
// ...
if(c != b) c = -(b / a) + 2 * b;
}
编译器将把涉及到complex数的各种运算转变为适当的函数调用。例如,c != b 的意思是 operator !=(c, b),而 1/a 的意思是operator/(complex(1), a)。
大部分(但并不是全部)模块表示为用户定义类型更好一些。
🔚